home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 19 / CU Amiga Magazine's Super CD-ROM 19 (1998)(EMAP Images)(GB)[!][issue 1998-02].iso / CUCD / Programming / LEDA / source / src / arith / idiv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-16  |  10.1 KB  |  512 lines

  1. /*******************************************************************************
  2. +
  3. +  LEDA  3.1c
  4. +
  5. +
  6. +  idiv.c
  7. +
  8. +
  9. +  Copyright (c) 1994  by  Max-Planck-Institut fuer Informatik
  10. +  Im Stadtwald, 6600 Saarbruecken, FRG     
  11. +  All rights reserved.
  12. *******************************************************************************/
  13.  
  14.  
  15.  
  16. /*    Umstellung auf PLACEadd etc., RD, 24.9.91    */
  17. /*    Normalisieren fuer die Division durch Shifts.    */
  18. /*    31.8.92, RD, Fehler in Idiv korrigiert: bb, one nicht
  19.         zerstoert (Hinweis von H.B. Eggenstein vom 10.8.92)
  20. */
  21.  
  22. #include <LEDA/impl/iint.h>
  23. #include <LEDA/impl/iloc.h>
  24.  
  25. static void normdiv(u, v, q, ul, vl)
  26.     register pPLACE u, v;
  27.     pPLACE q;
  28.     int ul;
  29.     register int vl;
  30. /* u, v sind verschiedene Integer.vec der Laengen ul, vl >=2, die fuer 
  31.    die Division u/v normiert sind. Das heisst auch, dass 
  32.    v[vl-1] > u[ul-1] ist. u[ul-1]=0 ist zugelassen. v ist nicht 0. 
  33.    Zurueckgegeben wird der Rest in u und der Quotient in q, die Laenge
  34.    von q muss groesser oder gleich ul-vl+1 sein. */
  35. {   register int j;
  36.     for (j=ul-1; j>=vl; j--) {
  37.     PLACE qdach, h, l, carry, help;
  38.     if (u[j]==v[vl-1]) {
  39.         qdach=RADIXMINUSONE;
  40.         /* (h, l) = (v[vl-2] - u[j-1])*RADIX - u[j-2] - 1 */
  41.         carry=PLACEsub(0, u[j-2], 1, &l);
  42.         carry=PLACEsub(v[vl-2], u[j-1], carry, &h);
  43.         if (!carry) {
  44.         /* (h, l) -= (v[vl-1]*RADIX + v[vl-2]) */
  45.         carry=PLACEsub(l, v[vl-2], carry, &l);
  46.         carry=PLACEsub(h, v[vl-1], carry, &h);
  47.         while (!carry) {
  48.             qdach-=1;
  49.             carry=PLACEsub(l, v[vl-2], carry, &l);
  50.             carry=PLACEsub(h, v[vl-1], carry, &h);
  51.         }
  52.         }
  53.     } else {
  54.         help=PLACEdiv(u[j], u[j-1], v[vl-1], &qdach);
  55.         /* (h, l) = v[vl-2]*qdach - help*RADIX - u[j-2] - 1; */
  56.         h=PLACEmul(qdach, v[vl-2], 0, &l);
  57.         carry=PLACEsub(l, u[j-2], 1, &l);
  58.         carry=PLACEsub(h, help, carry, &h);
  59.         while (!carry) {
  60.         qdach-=1;
  61.             carry=PLACEsub(l, v[vl-2], carry, &l);
  62.             carry=PLACEsub(h, v[vl-1], carry, &h);
  63.         }
  64.     }
  65.     /* Nun ist qdach bestimmt, und hoechstens 1 zu gross */
  66.     carry=vecmulsub(u+j-vl, v, qdach, vl);
  67.     if (carry) {        /* Addiere v zurueck */
  68.         qdach-=1;
  69.         carry=vecaddto(u+j-vl, v, vl);
  70.         PLACEadd(u[j], 0, carry, &u[j]);    /* Ignoriere carry */
  71.     }
  72.     q[j-vl]=qdach;
  73.     }        /* j-Schleife */
  74.     return;
  75. }        /* normdiv */
  76.  
  77. static PLACE norm_vecsli(u, a, toshift, count)
  78.     PLACE *u, *a;
  79.     int toshift, count;
  80. /* 0<=toshift<=LOGPLACE-1; */
  81. {    PLACE accu, help;
  82.     int i, bleft = LOGPLACE - toshift;
  83.  
  84.     if ( ! toshift ) {
  85.         for (i=0; i<count; i++)
  86.             u[i]=a[i];
  87.         return 0;
  88.     }
  89.     accu = 0;
  90.     for ( i=0; i<count; i++ ) {
  91.         help = a[i];
  92.         accu |= (help<<toshift);
  93.         u[i]=accu;
  94.         accu=help>>bleft;
  95.     }
  96.     return accu;
  97. }        /* norm_vecsli */
  98.  
  99. static void norm_vecsri(a, u, toshift, count)
  100.     PLACE *a, *u;
  101.     int toshift, count;
  102. /* 0<=toshift<=LOGPLACE-1; */
  103. {    PLACE accu, help;
  104.     int i, bleft=LOGPLACE-toshift;
  105.  
  106.     if ( ! toshift ) {
  107.         for (i=0; i<count; i++)
  108.             a[i]=u[i];
  109.         return;
  110.     }
  111.     accu=u[0];
  112.     accu>>=toshift;
  113.     for ( i=1; i<count; i++ ) {
  114.         help=u[i];
  115.         accu|=(help<<bleft);
  116.         a[i-1]=accu;
  117.         accu=help>>toshift;
  118.     }
  119.     a[count-1]=accu;
  120. }        /* norm_vecsri  */
  121.  
  122.  
  123. /*******************************************************/
  124.  
  125. #ifdef __GNUC__
  126. PLACE uIdiasP(Integer *a, PLACE b)
  127. #else
  128. PLACE uIdiasP(a, b)
  129.     register pInteger a;
  130.     register PLACE b;
  131. #endif
  132. {    register PLACE rem;
  133.     if (!a->length)
  134.         return 0;
  135.     rem=vecdiv(a->vec, a->vec, b, a->length);
  136.     if (!a->vec[a->length-1])
  137.         a->length--;
  138.     return rem;
  139. }    /* uIdiasP */
  140.  
  141. #ifdef __GNUC__
  142. PLACE IdiasP(Integer *a, PLACE b)
  143. #else
  144. PLACE IdiasP(a, b)
  145.     register pInteger a;
  146.     register PLACE b;
  147. #endif
  148. {    register PLACE rem;
  149.     Integer one;
  150.     if (!a->length)
  151.         return 0;
  152.     rem=vecdiv(a->vec, a->vec, b, a->length);
  153.     if (!a->vec[a->length-1])
  154.         a->length--;
  155.     if (a->sign==PLUS)
  156.         return rem;
  157.     if (!rem)
  158.         return rem;
  159.     cIasint(&one, 1);
  160.     ImiasI(a, &one);
  161.     dI(&one);
  162.     return b-rem;
  163. }    /* IdiasP */
  164.  
  165. #ifdef __GNUC__
  166. PLACE uIasIdiP(Integer *q, const Integer *a, PLACE b)
  167. #else
  168. PLACE uIasIdiP(q, a, b)
  169.     register pInteger q;
  170.     register const Integer *a;
  171.     register PLACE b;
  172. #endif
  173. {    register PLACE rem;
  174.     register int nl;
  175.     if (q==a)
  176.         return uIdiasP(q, b);
  177.     if (!a->length) {
  178.         Iasint(q, 0);
  179.         return 0;
  180.     }
  181.     nl=a->length;
  182.     if (nl>q->maxlength) {
  183.         delvec(q->vec, q->maxlength);
  184.         q->maxlength=nl;
  185.         q->vec=newvec(&q->maxlength);
  186.     }
  187.     rem=vecdiv(q->vec, a->vec, b, a->length);
  188.     if (q->vec[a->length-1])
  189.         q->length=a->length;
  190.     else
  191.         q->length=a->length-1;
  192.     q->sign=PLUS;
  193.     return rem;
  194. }    /* uIasIdiP */
  195.  
  196. #ifdef __GNUC__
  197. PLACE IasIdiP(Integer *q, const Integer *a, PLACE b)
  198. #else
  199. PLACE IasIdiP(q, a, b)
  200.     register pInteger q;
  201.     register const Integer *a;
  202.     register PLACE b;
  203. #endif
  204. {    register PLACE rem;
  205.     register int nl;
  206.     Integer one;
  207.     if (q==a)
  208.         return IdiasP(q, b);
  209.     if (!a->length) {
  210.         Iasint(q, 0);
  211.         return 0;
  212.     }
  213.     nl=a->length;
  214.     if (nl>q->maxlength) {
  215.         delvec(q->vec, q->maxlength);
  216.         q->maxlength=nl;
  217.         q->vec=newvec(&q->maxlength);
  218.     }
  219.     rem=vecdiv(q->vec, a->vec, b, a->length);
  220.     if (q->vec[a->length-1])
  221.         q->length=a->length;
  222.     else
  223.         q->length=a->length-1;
  224.     if (a->sign==PLUS) {
  225.         q->sign=PLUS;
  226.         return rem;
  227.     }
  228.     q->sign=MINUS;
  229.     if (!rem)
  230.         return rem;
  231.     cIasint(&one, 1);
  232.     ImiasI(q, &one);
  233.     dI(&one);
  234.     return b-rem;
  235. }    /* IasIdiP */
  236.  
  237. /*************************************************/
  238.  
  239. void uIdiv(q, r, a, b)
  240.     pInteger q, r;
  241.     const Integer *a, *b;
  242. /* Division mit Rest, a=bq+r. */
  243. {   register pPLACE u, v;
  244.     register int ul, vl;
  245.     int unl, vnl, toshift;
  246.     register int m;
  247.     register int i;
  248.     PLACE help, carry;
  249.  
  250.     vl=b->length;
  251.     m=a->length-vl;
  252.     if (m<0) {
  253.     IasI(r, a);
  254.     r->sign=PLUS;
  255.     Iasint(q, 0);
  256.     return;
  257.     }
  258.     if (vl<=1) {
  259.     register PLACE rem;
  260.     if (!vl)
  261.         Ierror("uIdiv: division by zero");
  262.     rem=uIasIdiP(q, a, b->vec[0]);
  263.     *(r->vec)=rem;
  264.     if (rem)
  265.         r->length=1;
  266.     else
  267.         r->length=0;
  268.     r->sign=PLUS;
  269.     return;
  270.     }
  271.     /* Hilfsvariablen bereitstellen */
  272.     ul=a->length+1;
  273.     unl=ul;
  274.     u=newvec(&unl);
  275.     vnl=vl;
  276.     v=newvec(&vnl);
  277.     /* a, b normalisieren */
  278.     help=b->vec[vl-1];
  279.     toshift=0;
  280.     while ( !( help >> (LOGPLACE-1)) ) {
  281.     help<<=1;
  282.     toshift++;
  283.     }
  284.     u[ul-1]=norm_vecsli(u, a->vec, toshift, ul-1);
  285.     norm_vecsli(v, b->vec, toshift, vl);
  286.     /* eigentliche Division */
  287.     if (m+1>q->maxlength) {
  288.     delvec(q->vec, q->maxlength);
  289.     q->maxlength=m+1;
  290.     q->vec=newvec(&q->maxlength);
  291.     }
  292.     normdiv(u, v, q->vec, ul, vl);
  293.     /* Rest zurueckgewinnen */
  294.     if (vl>r->maxlength) {
  295.     delvec(r->vec, r->maxlength);
  296.     r->maxlength=vl;
  297.     r->vec=newvec(&r->maxlength);
  298.     }
  299.     norm_vecsri(r->vec, u, toshift, vl);
  300.     delvec(u, unl);
  301.     i=vl-1; 
  302.     u=r->vec;
  303.     while(!u[i] && i>=0)
  304.     i--;
  305.     r->length=i+1;
  306.     r->sign=PLUS;
  307.     /* Quotient auf Standardform */
  308.     if (q->vec[m])
  309.     q->length=m+1;
  310.     else
  311.     q->length=m;
  312.     q->sign=PLUS;
  313.     delvec(v, vnl);
  314. }        /* uIdiv */
  315.  
  316. /*************************************************/
  317.  
  318. void Idiv(q, r, a, b)
  319.     pInteger q, r;
  320.     const Integer *a, *b;
  321. /* Division mit Rest, a=bq+r. */
  322. {   register pPLACE u, v;
  323.     register int ul, vl;
  324.     int unl, vnl, toshift;
  325.     register int m;
  326.     register int i;
  327.     PLACE help, carry;
  328.     BOOLEAN usebb=FALSE;
  329.     Integer bb, one;
  330.  
  331.     vl=b->length;
  332.     m=a->length-vl;
  333.     if (m<0) { /* dann sind a, b verschiedene Variablen */
  334.     if (a->sign==PLUS) {
  335.         IasI(r, a);
  336.         Iasint(q, 0);
  337.         return;
  338.     }
  339.     if (b->sign==PLUS) {
  340.         IasIplI(r, a, b);
  341.         Iasint(q, -1);
  342.         return;
  343.     } else {
  344.         IasImiI(r, a, b);
  345.         Iasint(q, 1);
  346.         return;
  347.     }    
  348.     }        /* m<0 */
  349.     /* Sonderfall: Divisor einstellig */
  350.     if (vl<=1) {
  351.     register PLACE rem;
  352.     if (!vl)
  353.         Ierror("Idiv: Division by zero");
  354.     rem=IasIdiP(q, a, b->vec[0]);
  355.     *(r->vec)=rem;
  356.     if (rem)
  357.         r->length=1;
  358.     else
  359.         r->length=0;
  360.     r->sign=PLUS;
  361.     q->sign^=b->sign;
  362.     return;
  363.     }
  364.     /* Hilfsvariablen bereitstellen */
  365.     ul=a->length+1;
  366.     unl=ul;
  367.     u=newvec(&unl);
  368.     vnl=vl;
  369.     v=newvec(&vnl);
  370.     /* a zu u, b zu v normalisieren */
  371.     help=b->vec[vl-1];
  372.     toshift=0;
  373.     while ( !( help >> (LOGPLACE-1)) ) {
  374.     help<<=1;
  375.     toshift++;
  376.     }
  377.     u[ul-1]=norm_vecsli(u, a->vec, toshift, ul-1);
  378.     norm_vecsli(v, b->vec, toshift, vl);
  379.     /* eigentliche Division */
  380.     if (a->sign==MINUS) {
  381.     if ((b==r)||(b==q)) {
  382.         usebb=TRUE;
  383.         cIasI(&bb, b);
  384.     }
  385.     }
  386.     if (m+1>q->maxlength) {
  387.     delvec(q->vec, q->maxlength);
  388.     q->maxlength=m+1;
  389.     q->vec=newvec(&q->maxlength);
  390.     }
  391.     normdiv(u, v, q->vec, ul, vl);
  392.     /* Rest zurueckgewinnen */
  393.     if (vl>r->maxlength) {
  394.     delvec(r->vec, r->maxlength);
  395.     r->maxlength=vl;
  396.     r->vec=newvec(&r->maxlength);
  397.     }
  398.     norm_vecsri(r->vec, u, toshift, vl);
  399.     delvec(u, unl);
  400.     i=vl-1; 
  401.     u=r->vec;
  402.     while(!u[i] && i>=0)
  403.     i--;
  404.     r->length=i+1;
  405.     /* Quotient auf Standardform */
  406.     if (q->vec[m])
  407.     q->length=m+1;
  408.     else
  409.     q->length=m;
  410.     delvec(v, vnl);
  411.     /* Rest positiv, auf a==bq+r normalisieren. */
  412.     if (a->sign==PLUS) {
  413.     if (!(q->length))
  414.         q->sign=PLUS;
  415.     else
  416.         q->sign=b->sign;
  417.         r->sign=PLUS;
  418.         if (usebb)
  419.          {dI(&bb);}
  420.     return;
  421.     }
  422.     if (!r->length) {
  423.     if (!q->length)
  424.         q->sign=PLUS;
  425.     else
  426.         q->sign=a->sign^b->sign;
  427.     r->sign=PLUS;
  428.         if (usebb)
  429.          {dI(&bb);}
  430.     return;
  431.     }
  432.     cIasint(&one, 1);
  433.     if (!usebb) {
  434.         if (b->sign==PLUS) {
  435.         r->sign=MINUS;
  436.         IplasI(r, b);
  437.         q->sign=PLUS;
  438.         IplasI(q, &one);
  439.         q->sign=MINUS;
  440.             dI(&one);
  441.         return;
  442.     } else {
  443.         r->sign=MINUS;
  444.         ImiasI(r, b);
  445.         q->sign=PLUS;
  446.         IplasI(q, &one);
  447.             dI(&one);
  448.         return;
  449.     }
  450.     } else {
  451.         if (bb.sign==PLUS) {
  452.         r->sign=MINUS;
  453.         IplasI(r, &bb);
  454.         q->sign=PLUS;
  455.         IplasI(q, &one);
  456.         q->sign=MINUS;
  457.             dI(&bb); 
  458.             dI(&one);
  459.         return;
  460.     } else {
  461.         r->sign=MINUS;
  462.         ImiasI(r, &bb);
  463.         q->sign=PLUS;
  464.         IplasI(q, &one);
  465.             dI(&bb); 
  466.             dI(&one);
  467.         return;
  468. }   }   }    /* Idiv */
  469.  
  470. /*****************************************/
  471.  
  472. void IasIdiI(q, a, b)
  473.     pInteger q;
  474.     const Integer *a, *b;
  475. /* Division, Quotient */
  476. {    Integer r;
  477.     cI(&r);
  478.     Idiv(q, &r, a, b);
  479.     dI(&r);
  480. }
  481.  
  482. void IdiasI(q, b)
  483.     pInteger q;
  484.     const Integer *b;
  485. /* Division, Quotient */
  486. {    Integer r;
  487.     cI(&r);
  488.     Idiv(q, &r, q, b);
  489.     dI(&r);
  490. }
  491.  
  492. void IasIreI(r, a, b)
  493.     pInteger r;
  494.     const Integer *a, *b;
  495. /* Division, Rest */
  496. {    Integer q;
  497.     cI(&q);
  498.     Idiv(&q, r, a, b);
  499.     dI(&q);
  500. }
  501.  
  502. void IreasI(r, b)
  503.     pInteger r;
  504.     const Integer *b;
  505. /* Division, Rest */
  506. {    Integer q;
  507.     cI(&q);
  508.     Idiv(&q, r, r, b);
  509.     dI(&q);
  510. }
  511.